package org.example.iot;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class Test0x0199 {

    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup worker = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(worker);
        bootstrap.option(NioChannelOption.TCP_NODELAY, true);
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                    //和服务器建立连接之后的回调
                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        System.out.println("连接建立");
                        //执行登录
                        byte[] loginBytes = ByteBufUtil.decodeHexDump("028f525c6500990001014457475a434a59323331313038393939322e30322e30303031015b525c6538363531333730363131313638383934363030383435343337303332383338393836303443353130323232303237333238331f3c1f2c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009f130d0a");
                        ctx.writeAndFlush(Unpooled.buffer().writeBytes(loginBytes));
                        TimeUnit.SECONDS.sleep(5);


                        /**
                         * 025034dc5f002b000202010101014457475a434a59323331323138313032010101014457475a434a5932333132313831303376b50d0a
                         */
                        //上报传感器信息
                        //头部
                        byte[] bytes1 = ByteBufUtil.decodeHexDump("025034dc5f");

                        ByteBuf byteBuf= ByteBufAllocator.DEFAULT.buffer();
                        byteBuf.writeBytes(bytes1);
                        //数据长度 = 指令码 + 传感器数量 + 传感器信息
                        byteBuf.writeShort(2+1+(20*1));
                        //写入指令码
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0002"));
                        //写入传感器数量
                        byteBuf.writeByte(1);
                        //写入20字节445747
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("01010101"));
                        byteBuf.writeBytes("DWGZCJY241111111".getBytes(StandardCharsets.UTF_8));


                        //写入CRE
                        byte[] crcBytes = crc16CCITTFalse(ByteBufUtil.getBytes(byteBuf));
                        byteBuf.writeBytes(crcBytes);
                        //写入尾部
                        byteBuf.writeBytes(ByteBufUtil.decodeHexDump("0d0a"));
                        ctx.writeAndFlush(byteBuf);

                        /**
                         * 上传数据包
                         */
                        byte[] bytes = ByteBufUtil.decodeHexDump("02C551F16403CA0199B543F164770300004C2FD6BA1BA5263C32377E3FD850C5BA3C3D253CC9467E3FA37ECDBA4AA4233C133D7E3FA724EBBA43EC273CED2A7E3F3BDADDBA4C802B3C21347E3FC2E0F5BA5AE7293C274C7E3F109CE9BAE7DB273C46467E3F717FE4BA619F253C493B7E3F109CE9BA16DB243CE64B7E3F0708E6BA48BF223C71427E3F69BEEFBA03AA243CF32B7E3F21F1E1BA4007273C0F317E3FA551DCBAA5AB2A3C525F7E3F3A07CFBA1F6F283CCF477E3FBF3AD8BA851C253C702B7E3F109CE9BA1BA5263C5A3E7E3F68EBE0BA19C0253C24407E3F201ED3BA0A59273C23297E3FE2B7D7BA89E6263C1E3F7E3F0FC9DABA3E22263C9A607E3F602AECBA6B33293CC3457E3FEFF1F8BADB592A3C0A307E3FB94CF2BAC279273C963D7E3FB779E3BA068F253CF14D7E3FAD12D1BAD0E0253C073B7E3FD262DFBAAC63263CBB4F7E3FC10DE7BA4AA4233C6B417E3FA551DCBA16DB243C84237E3F9CBDD8BA43EC273CC0397E3F201ED3BA43EC273C9F4A7E3FD923D4BAE9C0283C96547E3FB94CF2BA8EB0283C5D4A7E3F3BDADDBA43EC273CBE447E3F0FC9DABA9383233C963D7E3FBF3AD8BA9568243C292A7E3FD262DFBA6669273C51317E3F3DADECBA0A59273C35437E3FD335EEBAD4AA273CAD587E3F5796E8BAD0E0253C71427E3F7A13E8BA8052233CBA217E3F2A85E5BA5153263CAC417E3F9D90E7BA47B6293C4F537E3FA37ECDBA4A9B2A3CE04A7E3F028FB9BAD2C5263C08527E3F521DBCBAA3CF223CD73D7E3F0C23BDBA2442233C53267E3F521DBCBA9F05213C7B2D7E3F9329D5BA4AA4233C40457E3F9329D5BA3E22263C93487E3F3246DABA376A2A3C9C557E3F5969F7BAC8282A3CBB4F7E3FD508FDBA4C89243CAF367E3FA8F7F9BAC931233C2F2B7E3F4FD5F3BABF94263C603F7E3F3A07CFBA5802293C85517E3FEC4BDBBAD2C5263C7D5B7E3F5D84CEBA76B5263CCC3B7E3F55C3D9BA14F6233C0C257E3F3BDADDBABBCA243C98327E3FC10DE7BA5338273C46467E3FEC4BDBBAD4AA273C415C7E3FD850C5BAE311263C475D7E3FED1EEABA0874263C02517E3F83A7EBBAAC63263CED2A7E3F8D3BEFBA3773233C59277E3F55C3D9BA1211233C65407E3F185DDEBA9C17273C3C5B7E3FC8CEDBBA14ED2A3C274C7E3FD923D4BAB312293CA13F7E3F717FE4BA2727243C0B477E3F29B2D6BA290C253CA81E7E3F15B7C0BA2BF1253C384F7E3FF239C1BAAA7E253CE6627E3FAB3FC2BAE02C253C9B3E7E3F8995D1BA7E6D223C3D397E3F0DF6CBBA4C89243CDD3E7E3F0FC9DABA4F6E253C5D4A7E3F7A13E8BABDAF253CF6377E3F09DBF4BA19C0253C13547E3FF5DFDEBA0A59273CF8657E3F81A60D0A");
                        ByteBuf buffer = Unpooled.buffer();
                        buffer.writeBytes(bytes);
                        ctx.writeAndFlush(buffer);

                    }
                });
            }
        });
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9876).sync();
        Channel channel = channelFuture.channel();

    }

    public static byte[] crc16CCITTFalse(byte[] bytes) {
        int crc = 0xffff; // initial value
        int polynomial = 0x1021; // poly value
        for (int index = 0; index < bytes.length; index++) {
            byte b = bytes[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit){
                    crc ^= polynomial;
                }
            }
        }
        crc &= 0xffff;
        return new byte[] { (byte) ((0xff00 & crc) >> 8),(byte) (0xff & crc)  };
    }

}
